package cn.nawang.ebeim.server.service;

import cn.nawang.ebeim.server.constants.Config;
import cn.nawang.ebeim.server.util.PathUtil;
import com.alibaba.fastjson.util.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by GanJc on 2015-11-10 17:34
 */
public class LocalStorageService implements StorageService {

    private static final Logger LOG = LoggerFactory.getLogger(LocalStorageService.class);

    @Override
    public void uploadFile(String dataSourceId, String signature) {
        String localPath = PathUtil.getFileLocalPathUpload(dataSourceId, signature);
        String serverPath = PathUtil.getFileServerPath(dataSourceId, signature);
        String serverDirectoryPath = PathUtil.getFileServerDirectory(dataSourceId);
        this.moveFileLocalToServer(localPath, serverPath, serverDirectoryPath, signature);
        LOG.info("上传数据文件成功，localPath：" + serverPath + "，localPath：" + localPath + "，时间："
                + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
    }

    @Override
    public void downloadFile(String dataSourceId, String signature) {
        String localPath = PathUtil.getFileLocalPathDownload(dataSourceId, signature);
        String serverPath = PathUtil.getFileServerPath(dataSourceId, signature);
        String localDirectoryPath = PathUtil.getFileLocalDirectoryDownload(dataSourceId);
        this.moveFileServerToLocal(localPath, serverPath, localDirectoryPath, signature);
        LOG.info("下载数据文件成功，localPath：" + serverPath + "，localPath：" + localPath + "，时间："
                + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
    }

    @Override
    public void uploadVersionTree(String dataSourceId, String version) {
        String localPath = PathUtil.getVersionTreeLocalPathUpLoad(dataSourceId, version);
        String serverPath = PathUtil.getVersionTreeServerPath(dataSourceId, version);
        String serverDirectoryPath = PathUtil.getVersionTreeServerDirectory(dataSourceId);
        this.moveFileLocalToServer(localPath, serverPath, serverDirectoryPath, version);
        LOG.info("上传版本树文件成功，localPath：" + serverPath + "，localPath：" + localPath + "，时间："
                + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
    }

    @Override
    public void downloadVersionTree(String dataSourceId, String version) {
        String localPath = PathUtil.getVersionTreeLocalPathDownLoad(dataSourceId, version);
        String serverPath = PathUtil.getVersionTreeServerPath(dataSourceId, version);
        String localDirectoryPath = PathUtil.getVersionTreeLocalDirectoryDownLoad(dataSourceId);
        this.moveFileServerToLocal(localPath, serverPath, localDirectoryPath, version);
        LOG.info("下载版本树文件成功，localPath：" + serverPath + "，localPath：" + localPath + "，时间："
                + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
    }


    private void moveFileLocalToServer(String localPath, String serverPath, String directoryPath,
                                      String fileName) {
        File dir = new File(directoryPath);
        // 创建上级目录
        if (!dir.exists()) {
            dir.mkdirs();
        }
        File file = new File(directoryPath + File.separator + Config.TEMP_FILE_PREFIX + fileName);
        LOG.info("本地文件" + fileName + " )存到" + directoryPath);
        LOG.info("未重命名前的文件名称：" + directoryPath + File.separator + Config.TEMP_FILE_PREFIX + fileName
                + "，时间：" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        // 创建目标文件
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        File localFile = new File(localPath);
        this.fileChannelCopy(localFile, file);
        String trueFileName = fileName.substring(fileName.lastIndexOf('_')+1, fileName.length());
        serverPath = directoryPath + File.separator + trueFileName;

        boolean flag = file.renameTo(new File(serverPath));
        if(flag){
            LOG.info("云端文件" + directoryPath + File.separator + Config.TEMP_FILE_PREFIX
                    + Config.UPLOAD_FILE_PREFIX + fileName + "重命名为："+serverPath);
        }else{
            LOG.info("云端文件" +directoryPath + File.separator + Config.TEMP_FILE_PREFIX
                    + Config.UPLOAD_FILE_PREFIX + fileName+"重命名失败");
        }

    }

    private void moveFileServerToLocal(String localPath, String serverPath, String directoryPath,
                                      String fileName) {
        File dir = new File(directoryPath);
        // 创建上级目录
        if (!dir.exists()) {
            dir.mkdirs();
        }
        File file = new File(directoryPath + File.separator + Config.TEMP_FILE_PREFIX + fileName);
        LOG.info("本地文件" + fileName + " )存到" + directoryPath);
        LOG.info("未重命名前的文件名称：" + directoryPath + File.separator + Config.TEMP_FILE_PREFIX + fileName
                + "，时间：" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        // 创建目标文件
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        File serverFile = new File(serverPath);
        fileChannelCopy(serverFile, file);
        boolean flag = new File(directoryPath + File.separator + Config.TEMP_FILE_PREFIX + fileName)
                .renameTo(new File(localPath));
    }

    private void fileChannelCopy(File s, File t) {
        DataInputStream dis=null;
        DataOutputStream dos = null;
        try {
            dis =new DataInputStream(new FileInputStream(s));
            dos =new DataOutputStream(new FileOutputStream(t));
            byte[] bytes = new byte[4096];
            int length;
            while ((length = dis.read(bytes)) != -1) {
                dos.write(bytes, 0, length);
                dos.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            IOUtils.close(dis);
            IOUtils.close(dos);
        }
    }

}
